package com.iims.flowable.listener;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.iims.common.utils.spring.SpringUtils;
import com.iims.flowable.flow.ObjectUtils;
import com.iims.flowable.flow.domain.FlowListenerHandle;
import com.iims.flowable.flow.domain.FlowTaskForm;
import com.iims.flowable.mapper.FlowBusinessConfMapper;
import com.iims.flowable.service.impl.FlowTaskFormServiceImpl;
import com.iims.framework.manager.AsyncManager;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.delegate.Expression;
import org.flowable.engine.ManagementService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.impl.ManagementServiceImpl;
import org.flowable.engine.impl.RuntimeServiceImpl;
import org.flowable.engine.impl.cmd.SetProcessInstanceBusinessKeyCmd;
import org.flowable.engine.runtime.ProcessInstance;

import javax.annotation.PostConstruct;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;

/**
 * 创建对象的执行监听器
 *
 * @author fanpei
 * @date 2021/7/6 9:27
 */
@Slf4j
//@Component
@Deprecated
public class CreateBusinessObjListener /*implements ExecutionListener*/ {
    private static FlowTaskFormServiceImpl cmistaskFormService;
    private static FlowBusinessConfMapper handleConfMapper;
    private static ManagementService managementService;
    private static RuntimeService runtimeService;
    private Expression taskHandleKey;

    @PostConstruct
    public void init() {
        runtimeService = SpringUtils.getBean(RuntimeServiceImpl.class);
        managementService = SpringUtils.getBean(ManagementServiceImpl.class);
        cmistaskFormService = SpringUtils.getBean(FlowTaskFormServiceImpl.class);
        handleConfMapper = SpringUtils.getBean(FlowBusinessConfMapper.class);
    }

    //@Override
    public void notify(DelegateExecution execution) {
        //异步执行，延迟获取事务提交的数据
        AsyncManager.me().execute(new TimerTask() {
            @Override
            public void run() {
                String processInstanceId = execution.getProcessInstanceId();
                String handleKey = (String) taskHandleKey.getValue(execution);
                if (StrUtil.isEmpty(handleKey))
                    return;
                FlowListenerHandle handleConf = handleConfMapper.selectOneByHandleKey(handleKey);
                if (null == handleConf) {
                    log.warn("[监听器创建对象] 配置的taskHandleKey值{}不存在，监听器:{}", handleKey);
                    return;
                }
                try {
                    FlowTaskForm taskForm = cmistaskFormService.getRenderedTaskFormWithDataJson(processInstanceId, handleConf.getFormKey());
                    if (null == taskForm) {
                        log.error("[监听器创建对象] 流程实例启动时未传入表单{}值", handleConf.getFormKey());
                        return;
                    }
                    Class<?> clazz = Class.forName(handleConf.getHandleClass());
                    Object service = SpringUtils.getBean(clazz);
                    if (service != null) {
                        //反射调用数据入库
                        Class<?> methodArgClass = Class.forName(handleConf.getHandleMethodEntity());
                        Method method = service.getClass().getMethod(handleConf.getHandleMethod(), methodArgClass);
                        Object targetObjEntity = JSONUtil.toBean(taskForm.formDataJsonStr(), methodArgClass);
                        initCreateUpdateBy(targetObjEntity, taskForm);
                        String bussinessKey = (String) method.invoke(service, targetObjEntity);

                        //设置业务KEY
                        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                                .processInstanceId(processInstanceId)
                                .processInstanceBusinessKey(bussinessKey).singleResult();
                        if (processInstance == null) {
                            SetProcessInstanceBusinessKeyCmd businessKeyCmd = new SetProcessInstanceBusinessKeyCmd(processInstanceId, bussinessKey);
                            managementService.executeCommand(businessKeyCmd);
                        }
                    }
                } catch (Exception e) {
                    log.error("创建对象监听器反射异常错误", e);
                }
            }
        }, 500, TimeUnit.MILLISECONDS);
    }

/*
    @Override
    public void notify(DelegateTask delegateTask) {

    }
*/

    /**
     * 初始化创建者和更新者
     *
     * @param targetObjEntity
     * @param taskForm
     */
    private void initCreateUpdateBy(Object targetObjEntity, FlowTaskForm taskForm) {
        try {
            Method getCreateByMethod = targetObjEntity.getClass().getMethod("getCreateBy");
            //region 处理创建人信息
            if (ObjectUtils.isEmpty(getCreateByMethod.invoke(targetObjEntity))) {
                Method setCreateByMethod = targetObjEntity.getClass().getMethod("setCreateBy", String.class);
                Method setCreateTimeMethod = targetObjEntity.getClass().getMethod("setCreateTime", Date.class);
                setCreateByMethod.invoke(targetObjEntity, taskForm.getCreateBy());
                setCreateTimeMethod.invoke(targetObjEntity, new Date());
            }

            Method getUpdateByMethod = targetObjEntity.getClass().getMethod("getUpdateBy");
            //region 处理创建人信息
            if (ObjectUtils.isEmpty(getUpdateByMethod.invoke(targetObjEntity))) {
                Method setUpdateMethod = targetObjEntity.getClass().getMethod("setUpdateBy", String.class);
                setUpdateMethod.invoke(targetObjEntity, taskForm.getCreateBy());
            }
            Method setUpdateTimeMethod = targetObjEntity.getClass().getMethod("setUpdateTime", Date.class);
            setUpdateTimeMethod.invoke(targetObjEntity, new Date());
        } catch (Exception e) {
            log.error("流程任务监听器创建任务,初始化创建者和更新者错误");
        }
    }
}
